<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			.node-info {
				position: absolute;
				display: none;
				border-radius: 0.5em;
				background: #555;
				
			}
			
			.node-info ul {
				margin: 0;
				padding: 0.5em;
				list-style: none;
			}
			
			.node-info ul li {
				color:#fff;
				font-size: 12px;
			}
		</style>
	</head>
	<body>
		<div id="tpContainer" style="overflow: hidden;"></div>
		<script type="text/javascript" src="js/jquery-1.11.0.min.js" ></script>
		<script src ="js/d3_3.2.8.js"></script>
		<script>
		
		    var imgMap = {
		   		'0':'img/clouds/cloud-province.png',
		   		'1':'img/clouds/cloud-city.png',
		   		'2':'img/clouds/cloud-county.png',
		   		'error-tip':'img/clouds/error-tip.png',
		   		'link-cut':'img/clouds/link-cut.png'
		    };
		
			var tpoption = {
				container:'#tpContainer',
				data:'clouds-tp.json',
				width:window.innerWidth || document.documentElement.clientWidth,
				height:window.innerHeight || document.documentElement.innerHeight
			};
			
			function TPChart(option){
				var _defaultOption = {
					width:300,
					height:300,
					data:'',
					container:''
				};
			
				option = $.extend(true, _defaultOption,option);
				
				this.width  = option.width;
				this.height = option.height;
				this.data   = option.data;//数据url或对象,必填
				this.container = option.container;//svg容器(node或者选择器)，必填
			}
			
			TPChart.prototype.render = function(nodes,lines){
				var _this = this,
					width = _this.width,
					height = _this.height,
					svg = d3.select(_this.container).append("svg")
						.attr("width",width)
						.attr("height",height)
						.style("pointer-events", "all"),
					graph = svg.append("g").attr("class","graph"),
					
					_g_lines = graph.selectAll("line.line")
					.data(lines)
					.enter()
					.append("g")
					.attr("class","line"),
					
					_g_nodes = graph.selectAll("g.node")
					.data(nodes)
					.enter()
					.append("g")
					.attr("class","node");
					
				_g_lines.append("line")
					.style('stroke',function(d){
						if(d.status == 0){
							return '#f76e5d';
						}else{
							return '#93c62d';
						}
					})
					.style("stroke-width",2);
						
					
				_g_nodes.append("image")
					.style("width",function(d){
						var width = 40;
						switch (d.type){
							case '0':
								width = 1.5*width;
								break;
							case '1':
								width = 1.2*width;
								break;
							default:
								break;
						}
						return width;
					})
					.style("height",function(d){
						var height = 40;
						switch (d.type){
							case '0':
								height = 1.5*height;
								break;
							case '1':
								height = 1.2*height;
								break;
							default:
								break;
						}
						return height;
					})
					.attr("xlink:href",function(d){
						return imgMap[d.type];
					});
					
				_g_nodes.append("text")
					.text(function(d){
						return d.name;
					})
					.style('font-size','12')
					.style('fill','#333');
					
				_g_nodes.each(function(d,i){
					var selection = d3.select(this);
					if(d.status == '0'){
						selection.append("g").attr("class","error-tip")
						.append("image").attr("xlink:href",function(d){
							return imgMap['error-tip'];
						});
					}
				});
				
				_g_lines.each(function(d,i){
					var _this = d3.select(this);
					if(d.netspeed && d.status != 0){
						_this.append("text")
							.text(d.netspeed)
							.style('fill','rgb(255,198,22)')
							.style('font-size','11');
							
						_this.append("rect")
							.attr("fill",function(d){
								return '#555';
							})
							.attr("width",function(d){
								return 2;
							})
							.attr("height",function(d){
								return 2;
							})
							.append("animate");
							
						_this.select("rect").append("animate");
					}else{
						_this.append("image")
						    .attr("xlink:href",function(){
								return imgMap['link-cut'];
							});
					}
				});
					
				var force = d3.layout.force()
						.nodes(nodes)
						.links(lines)
						.size([width, height])
						.linkDistance(function(d){
							var distance = 90;
							distance += distance*Math.random()*0.5;
							return distance;
						})
						.charge(-700)
						.start();

				//添加缩放行为
				svg.call(getZoomBehavior(graph));
				
				//添加拖拽行为
				_g_nodes.call(getDragBehavior(force));
				
				_g_nodes.on('mouseenter',function(d){
					d3.select(this).style("cursor","pointer");
					
					$(_this.container).append(createInfoTip(d));
						$(".node-info").css({
							left:d3.event.x+20,
							top:d3.event.y+20
						}).show();
				});
				
				_g_nodes.on('mouseleave',function(){
					$(".node-info").remove();
				});
				

				_g_nodes.on('dblclick.zoom',function(){
					window.location.href = './index2.html';
				});
				
				
				force.on("tick", function() {
					
					_g_lines.select("line").attr("x1",function(d){
					  	   return d.source.x;
					    })
					    .attr("y1",function(d){
					  	   return d.source.y;
					    })
					    .attr("x2",function(d){
					  	   return d.target.x;
					    })
					    .attr("y2",function(d){
					  	   return d.target.y;
					    });
					    
					    
					    
					_g_lines.select("image").attr("x",function(d){
				    	var x1 = d.source.x,
					    	x2 = d.target.x,
					    	x  = x1-(x1-x2)/2;
					    
						//线段二分之一处
						return x - 8;
				    })
				    .attr("y",function(d){
				    	var y1 = d.source.y,
					    	y2 = d.target.y,
					    	y  = y1-(y1-y2)/2;
					    
						//线段二分之一处
						return y - 15;
				    });
					    
					_g_lines.select("text")
						.attr('x',function(d){
							var x1 = d.source.x,
							    x2 = d.target.x,
							    halfX  = x1-(x1-x2)/2,
							    x3 = x1-(x1-halfX)/2;
							    
							//线段3分之-处
							return x3;
							//return d.source.x-(d.source.x-d.target.x)/2;
						})
						.attr('y',function(d){ 
							var y1 = d.source.y,
							    y2 = d.target.y,
							    halfY = y1-(y1-y2)/2,
							    y3 = y1-(y1-halfY)/2;
							
							//使文本与线段之间有一定间隙
							y3 = y3 - 5;
							
							return y3;
							//return y1-(y1-y2)/2;
						})
						.attr("transform",function(d){
							var x1 = d.source.x,
							    x2 = d.target.x,
							    y1 = d.source.y,
							    y2 = d.target.y,
							    x  = x1-(x1-x2)/2,
							    y  = y1-(y1-y2)/2,
							    rightAngleSide1 = Math.abs(y2-y1),
							    rightAngleSide2 = Math.abs(x2-x1),
							    _asin = 0,
							    _rotateAngle = 0,
							    x3 = x1-(x1-x)/2 ,
							    y3 = y1-(y1-y)/2;
							    
							    if(x1 < x2){
							    	_asin = (y2-y1)/Math.sqrt(Math.pow(rightAngleSide1,2)+Math.pow(rightAngleSide2,2));
							    	_rotateAngle = Math.asin(_asin)*180/Math.PI;
							    }else{
							    	_asin = (y1-y2)/Math.sqrt(Math.pow(rightAngleSide1,2)+Math.pow(rightAngleSide2,2));
							    	_rotateAngle = Math.asin(_asin)*180/Math.PI;
									_rotateAngle = _rotateAngle < 0?(180+_rotateAngle):-(180-_rotateAngle);
							    }
							    

							return 'rotate('+(_rotateAngle)+','+x3+' '+y3+')';//以线段的三分之一出为旋转焦点
							//return 'rotate('+(_rotateAngle)+','+x+' '+y+')';//以线段的二分之一处为旋转焦点
						});
						
					_g_lines.select("rect")
					    .attr('x',function(d){
					   		return d.source.x-1;
					    })
					    .attr('y',function(d){
					   		return d.source.y-1;
					    })
					    .selectAll('animate').each(function(d,i){
					    	if(i == 0){
					    		d3.select(this)
						    		.attr("attributeName",function(d){
										return 'x';
									})
						    		.attr("from",function(d){
										return d.source.x-1;
									})
								    .attr("to",function(d){
										return d.target.x;
									});
					    	}else{
					    		d3.select(this)
						    		.attr("attributeName",function(d){
										return 'y';
									})
						    		.attr("from",function(d){
										return d.source.y-1;
									})
								    .attr("to",function(d){
										return d.target.y;
									});
					    	}
					    	
					    	d3.select(this).attr("attributeType","XML")
								.attr("dur",function(d){
									return '1.5s';
								})
								.attr("repeatCount","indefinite");
							
						})
					
							
					    
					_g_nodes.attr("transform",function(d){
						
						var image = d3.select(this).select("image")[0][0],
						    halfWidth = parseFloat(image.style.width)/2,
						    halfHeight = parseFloat(image.style.height)/2;
						    
						return 'translate('+(d.x-halfWidth)+','+(d.y-halfHeight)+')';
						
					});
					
					_g_nodes.select("text").attr('dy',function(d){
							var image = this.previousSibling,
							    height = parseFloat(image.style.height),
							    fontSize = parseFloat(this.style.fontSize);
							    
							return height+1.5*fontSize;
						});
					
					_g_nodes.select(".error-tip").attr("transform",function(d){
						
						var image = this.parentNode.firstChild,
						    width = parseFloat(image.style.width);
						    
						return 'translate('+0.8*width+',0)';
						
					});
					
				});
				
				force.on("end", function() {
					
				});
				
			}
			
			TPChart.prototype.init = function(){
				
				var _this = this;
				if(typeStr(_this.data)=='[object string]'){
			    	d3.json(_this.data,function(error,data){
			    		if(error) throw error ;
			    		_this.data = data;
			    		_this.render(_this.data.nodes,_this.data.lines);
			    	});
			    }

			}
			
			function typeStr(obj){
		    	return Object.prototype.toString.call(obj).toLowerCase();
		    }
			
			//创建一个缩放行为
			function getZoomBehavior(g){
				
				return d3.behavior.zoom().scaleExtent([1,10]).on("zoom",zoomEvtFn);
				
				function zoomEvtFn(){
					g.attr("transform","translate("+d3.event.translate+")scale(" + d3.event.scale + ")");
				}
				
			}
			
			//创建一个拖拽行为
			function getDragBehavior(force){
				
				return d3.behavior.drag()
						.origin(function(d) {
							return d;
						})
						.on("dragstart", dragstart)
						.on("drag", dragging)
						.on("dragend", dragend);
				
				function dragstart(d) {
					d3.event.sourceEvent.stopPropagation();
					d3.select(this).classed("dragging", true);
					force.start();
				}
		
				function dragging(d) {
					d.x = d3.event.x;
					d.y = d3.event.y;
				}
		
				function dragend(d) {
					d3.select(this).classed("dragging", false);
				}
				
			}
			
			function createInfoTip(node){
				var html = '<div class="node-info"><ul>';
					html += '<li><span class="info-title">网络情况:</span><span class="info-content">正常</span></li>';
					html += '</ul></div>';
				
				return html;
			}
			
			//直线方程求x值
			function x_linearEquation(x1,y1,x2,y2,y){
				var a = y2-y1,
				    b = x1-x2,
				    c = x2*y1 - x1*y2;
				    
				return -(c+b*y)/a;
			}
			
			//直线方程求y值
			function y_linearEquation(x1,y1,x2,y2,x){
				var a = y2-y1,
				    b = x1-x2,
				    c = x2*y1 - x1*y2;
				    
				return -(c+a*y)/b;
			}
			
			var tp = new TPChart(tpoption);
			tp.init();
		</script>
	</body>
</html>
